package cn.cdeden.knowledge.service.impl;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.oss.enumd.OssBucketOneEnum;
import cn.cdeden.common.oss.enumd.OssModuleType;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.api.domain.dto.RemoteTemplate;
import cn.cdeden.knowledge.api.domain.page.PageQuery;
import cn.cdeden.knowledge.domain.EnterpriseFolderTree;
import cn.cdeden.knowledge.domain.dto.EnterpriseFilesTreeDto;
import cn.cdeden.knowledge.domain.dto.EnterpriseFolderTreeDto;
import cn.cdeden.knowledge.domain.dto.EnterpriseFolderTreeQueryParam;
import cn.cdeden.knowledge.domain.vo.EnterpriseFolderTreeVo;
import cn.cdeden.knowledge.mapper.EnterpriseFolderTreeMapper;
import cn.cdeden.knowledge.service.EnterpriseFilesTreeService;
import cn.cdeden.knowledge.service.EnterpriseFolderTreeService;
import cn.cdeden.knowledge.utils.PageUtil;
import cn.cdeden.resource.api.RemoteFileService;
import cn.cdeden.resource.api.domain.RemoteFile;
import cn.cdeden.system.api.domain.enums.FileTypeEnum;
import cn.cdeden.system.api.model.LoginUser;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* @author GW
* @date 2023-03-27
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = EnterpriseFolderTreeService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class EnterpriseFolderTreeServiceImpl extends ServiceImpl<EnterpriseFolderTreeMapper, EnterpriseFolderTree> implements EnterpriseFolderTreeService {

    // private final RedisUtils redisUtils;
    private final EnterpriseFolderTreeMapper enterpriseFolderTreeMapper;

    private final EnterpriseFilesTreeService enterpriseFilesTreeService;

    private final RemoteFileService remoteFileService;
    @Override
    public TableDataInfo<EnterpriseFolderTreeDto> queryAll(EnterpriseFolderTreeQueryParam query, Pageable pageable) {
        IPage<EnterpriseFolderTree> queryPage = PageUtil.toMybatisPage(pageable);
        QueryWrapper<EnterpriseFolderTree> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.isNull("parent_id");
        if (query.getRealName() != null && !query.getRealName().equals("")){
            predicate.eq("real_name",query.getRealName());
        }
        IPage<EnterpriseFolderTree> page = enterpriseFolderTreeMapper.selectPage(queryPage, predicate);
        TableDataInfo<EnterpriseFolderTree> build = TableDataInfo.build(page);
        return MapstructUtils.convertTableDataInfo(build,EnterpriseFolderTreeDto.class);
    }

    @Override
    public TableDataInfo<EnterpriseFolderTreeDto> queryAll(EnterpriseFolderTreeQueryParam query, PageQuery pageQuery) {

        QueryWrapper<EnterpriseFolderTree> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.isNull("parent_id");
        if (query.getRealName() != null && !query.getRealName().equals("")){
            predicate.eq("real_name",query.getRealName());
        }
        Page<EnterpriseFolderTree> enterpriseFolderTreeIPage = enterpriseFolderTreeMapper.selectPage(pageQuery.build(), predicate);
        TableDataInfo<EnterpriseFolderTree> build = TableDataInfo.build(enterpriseFolderTreeIPage);
        return MapstructUtils.convertTableDataInfo(build,EnterpriseFolderTreeDto.class);
    }

    @Override
    public List<EnterpriseFolderTreeDto> queryAll(EnterpriseFolderTreeQueryParam query){
        return MapstructUtils.convert(enterpriseFolderTreeMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), EnterpriseFolderTreeDto.class);
    }

    @Override
    public EnterpriseFolderTree getById(Long id) {
        return enterpriseFolderTreeMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public EnterpriseFolderTreeDto findById(Long id) {
        return MapstructUtils.convert(getById(id), EnterpriseFolderTreeDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createByEnterpriseId(EnterpriseFolderTreeVo enterpriseFolderTreeVo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        EnterpriseFolderTree enterpriseFolderTree = new EnterpriseFolderTree();
        enterpriseFolderTree.setRealName(enterpriseFolderTreeVo.getRealName());
        enterpriseFolderTree.setUrl(enterpriseFolderTreeVo.getUrl());
        enterpriseFolderTree.setRemark(enterpriseFolderTreeVo.getRemark());
        enterpriseFolderTree.setCreateId(String.valueOf(loginUser.getUserId()));
        enterpriseFolderTree.setCreateBy(loginUser.getUsername());
        this.save(enterpriseFolderTree);
        List<Long> enterpriseIds = enterpriseFolderTreeVo.getEnterpriseIds();
        for (Long enterpriseId : enterpriseIds) {
            createFolder(enterpriseId, String.valueOf(enterpriseFolderTree.getId()));
        }
    }

    private void createFolder(Long enterpriseId,String parentId){
        LoginUser loginUser = LoginHelper.getLoginUser();
        EnterpriseFilesTreeDto enterpriseFilesTreeDto = enterpriseFilesTreeService.getFolder(enterpriseId);
        EnterpriseFolderTree entity = MapstructUtils.convert(enterpriseFilesTreeDto, EnterpriseFolderTree.class);
        entity.setId(null);
        entity.setParentId(parentId);
        if (enterpriseFilesTreeDto.getType().equals(FileTypeEnum.FILE.getCode())){
            RemoteFile remoteFile = new RemoteFile();
            remoteFile.setOssId(Long.valueOf(enterpriseFilesTreeDto.getStorageId()));
            RemoteFile copyFile = remoteFileService.copyFile(remoteFile, OssBucketOneEnum.ENTERPRISE_TEMPLATE.getCode(), OssModuleType.Template);

            entity.setStorageId(String.valueOf(copyFile.getOssId()));
            entity.setEdition(copyFile.getVersionId());
            entity.setEditionName(copyFile.getVersionName());
        }
        entity.setCreateId(String.valueOf(loginUser.getUserId()));
        entity.setCreateBy(loginUser.getUsername());
        Boolean flag = this.save(entity);
        enterpriseFilesTreeDto.setId(entity.getId());
        for (EnterpriseFilesTreeDto child : enterpriseFilesTreeDto.getChildren()) {
            createFolder(child.getId(), String.valueOf(entity.getId()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(EnterpriseFolderTreeDto resources){
        EnterpriseFolderTree entity = MapstructUtils.convert(resources, EnterpriseFolderTree.class);
        boolean ret = this.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(Set<Long> ids){
        return removeByIds(ids) ;
    }

/*    public void deleteFolderAll(Long id){
        EnterpriseFolderTreeDto byId = findById(id);
        if (byId.getType().equals(TreeTypeEnum.FILE.getType())) fileStorageUtils.delete(Long.valueOf(byId.getStorageId()), StorageTypeEnum.find(byId.getType()));
        else if (byId.getType().equals(TreeTypeEnum.FOLDER.getType())){
            List<EnterpriseFolderTree> list = enterpriseFolderTreeMapper.lambdaQuery().eq(EnterpriseFolderTree::getParentId, byId.getId()).list();
            for (EnterpriseFolderTree enterpriseFolderTree : list) {
                enterpriseFolderTreeMapper.deleteById(enterpriseFolderTree.getId());
                deleteFolderAll(id);
            }
        }
    }*/

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id){
        Set<Long> set = new HashSet<>(1);
        set.add(id);
        return this.deleteByIds(set);
    }

    /*
    private void delCaches(Long id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Long> ids) {
        for (Long id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<EnterpriseFolderTreeDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (EnterpriseFolderTreeDto enterpriseFolderTree : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("父亲编号", enterpriseFolderTree.getParentId());
              map.put("文件编号", enterpriseFolderTree.getFileId());
              map.put("后缀名", enterpriseFolderTree.getSuffix());
              map.put("名称", enterpriseFolderTree.getRealName());
              map.put("上级路径", enterpriseFolderTree.getSuperiorsPath());
              map.put("路径", enterpriseFolderTree.getPath());
              map.put("类型", enterpriseFolderTree.getType());
              map.put("储存表id", enterpriseFolderTree.getStorageId());
              map.put("储存服务器类型", enterpriseFolderTree.getStorageType());
              map.put("文件大小", enterpriseFolderTree.getSize());
              map.put("关连状态", enterpriseFolderTree.getLinkingState());
                map.put(" attention",  enterpriseFolderTree.getAttention());
                map.put(" collection",  enterpriseFolderTree.getCollection());
                map.put(" isLock",  enterpriseFolderTree.getIsLock());
                map.put(" columnType",  enterpriseFolderTree.getColumnType());
              map.put("创建编号", enterpriseFolderTree.getCreateId());
              map.put("创建者", enterpriseFolderTree.getCreateBy());
              map.put("创建日期", enterpriseFolderTree.getCreateTime());
              map.put("更新编号", enterpriseFolderTree.getUpdateId());
              map.put("更新者", enterpriseFolderTree.getUpdateBy());
              map.put("更新时间", enterpriseFolderTree.getUpdateTime());
              map.put("删除编号", enterpriseFolderTree.getDeleteId());
              map.put("删除者", enterpriseFolderTree.getDeleteBy());
              map.put("删除时间", enterpriseFolderTree.getDeleteTime());
                map.put(" deleteType",  enterpriseFolderTree.getDeleteType());
              map.put("版本", enterpriseFolderTree.getEditionName());
              map.put("版本号", enterpriseFolderTree.getEdition());
                map.put(" fileEncode",  enterpriseFolderTree.getFileEncode());
              map.put("文件的MD5", enterpriseFolderTree.getFileMd5());
                map.put(" parentFile",  enterpriseFolderTree.getParentFile());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/

    //获得文件树
//    @Override
//    public EnterpriseFilesTreeDto getFolder(Long templateId){
//        if (ObjectUtil.isNull(templateId))throw new BadRequestException("模板id为空");
//        EnterpriseFolderTree byId = getById(templateId);
//        if (ObjectUtil.isNull(byId))throw new BadRequestException("模板文件夹不存在,请重新创建");
//        byId.setPath(ImageFileUrlUtil.imageFile(byId.getPath()));
//        EnterpriseFilesTree byId1 = enterpriseFilesTreeService.getById(byId.getParentId());
//        EnterpriseFilesTreeDto convert = ConvertUtil.convert(byId1, EnterpriseFilesTreeDto.class);
//        select(convert);
//        return convert;
//    }
//
//    public void select(EnterpriseFilesTreeDto enterpriseFilesTreeDto){
//        List<EnterpriseFilesTree> list = enterpriseFilesTreeService.lambdaQuery().eq(EnterpriseFilesTree::getParentId, enterpriseFilesTreeDto.getId()).list();
//        List<EnterpriseFilesTreeDto> convert = ConvertUtil.convertList(list, EnterpriseFilesTreeDto.class);
//        enterpriseFilesTreeDto.setChildren(convert);
//        for (EnterpriseFilesTreeDto enterpriseFilesTree : convert) {
//            select(enterpriseFilesTree);
//        }
//    }

    @Override
    public EnterpriseFolderTreeDto selectNext(Long id){
        if (ObjectUtil.isNull(id))throw new RuntimeException("id值为空");
        EnterpriseFolderTreeDto enterpriseFolderTreeDto = MapstructUtils.convert(getById(id), EnterpriseFolderTreeDto.class);
        setChildren(enterpriseFolderTreeDto);
        return enterpriseFolderTreeDto;
    }

    private void setChildren(EnterpriseFolderTreeDto parentTreeDto){
        List<EnterpriseFolderTree> list = enterpriseFolderTreeMapper.lambdaQuery().eq(EnterpriseFolderTree::getParentId, parentTreeDto.getId()).list();
        List<EnterpriseFolderTreeDto> convert = MapstructUtils.convert(list, EnterpriseFolderTreeDto.class);
        for (EnterpriseFolderTreeDto EnterpriseFolderTreeDto  : convert) {
            setChildren(EnterpriseFolderTreeDto);
            parentTreeDto.getChildren().add(EnterpriseFolderTreeDto);
        }
    }

}
